package model;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import lucene.PaperSearcher;

import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermEnum;
import org.apache.lucene.index.TermFreqVector;
import org.apache.lucene.store.FSDirectory;

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.ResultSet;
import com.mysql.jdbc.Statement;

import data.TestUserSelection;

public class BuildTitleModel {

	private String user;
	private Connection conn;

	private HashSet<String> tags = new HashSet<String>();
	private HashSet<String> holdoutPapers = new HashSet<String>();
	private HashSet<String> trainPapers = new HashSet<String>();

	private IndexReader reader;
	private PaperSearcher searcher;
	private final int termNum;

	public BuildTitleModel(String u, Connection c) throws Exception {
		this.user = u;
		this.conn = c;
		String path = "D:\\CityU\\project\\bibsonomy\\experiment\\" + user
				+ "\\index\\";

		File indexDir = new File(path);
		IndexReader reader = IndexReader.open(FSDirectory.open(indexDir), true);
		this.reader = reader;

		int cnt = 0;
		TermEnum terms = reader.terms();
		while (terms.next()) {
			cnt++;
		}
		this.termNum = cnt;
		this.searcher = new PaperSearcher(indexDir);
		initTrainPapers();
		initHoldoutPapers();
		initTags();

	}

	private void initHoldoutPapers() throws Exception {
		String path = "D:\\CityU\\project\\bibsonomy\\experiment\\" + user
				+ "\\test.txt";
		BufferedReader reader = new BufferedReader(new FileReader(path));
		String line = null;
		while ((line = reader.readLine()) != null) {
			line = line.trim();
			holdoutPapers.add(line);
		}
		reader.close();
	}

	private void initTrainPapers() throws Exception {
		String path = "D:\\CityU\\project\\bibsonomy\\experiment\\" + user
				+ "\\train.txt";
		BufferedReader reader = new BufferedReader(new FileReader(path));
		String line = null;
		while ((line = reader.readLine()) != null) {
			line = line.trim();
			trainPapers.add(line);
		}
		reader.close();
	}

	private void initTags() throws Exception {
		Statement stmt = null;
		ResultSet rs = null;

		try {
			stmt = (Statement) conn.createStatement();
			rs = (ResultSet) stmt
					.executeQuery("SELECT tag,content_id FROM TAS_NEW where user = '"
							+ user + "'");
			while (rs.next()) {
				String content_id = rs.getString("content_id");
				if (holdoutPapers.contains(content_id))
					continue;
				String tag = rs.getString("tag");
				tags.add(tag);
			}
		} finally {
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException sqlEx) {
				} // ignore
				rs = null;
			}

			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException sqlEx) {
				} // ignore
				stmt = null;
			}
		}
		System.out.println("total term num\t" + termNum + "\ttag num\t"
				+ tags.size());

	}
	
	public void clear() throws Exception{
		this.reader = null;
		this.searcher = null;
	}

	private List<Integer> retrieveUserPapersByTag(String tag, Statement stmt,
			ResultSet rs) throws Exception {
		List<Integer> list = new ArrayList<Integer>();

		if (tag.indexOf("\\") != -1)
			return list;
		tag = tag.replaceAll("'", "''");
		//tag = tag.replaceAll("\\", "\\\\");
		rs = (ResultSet) stmt
				.executeQuery("SELECT content_id FROM TAS_NEW where user = '"
						+ user + "' and " + "tag = '" + tag + "'");
		//HashSet<String> papers = new HashSet<String>();
		while (rs.next()) {
			String content_id = rs.getString("content_id");

			if (!trainPapers.contains(content_id))
				continue;

			int doc = searcher.retrieveDocByPid(content_id);
			list.add(doc);
		}
		return list;
	}

	public void build() throws Exception {

		Statement stmt = null;
		ResultSet rs = null;
		String path = "D:\\CityU\\project\\bibsonomy\\experiment\\" + user
				+ "\\tag_term_map.txt";
		BufferedWriter writer = new BufferedWriter(new FileWriter(path));

		try {
			stmt = (Statement) conn.createStatement();
			List<Integer> list = null;
			TermEnum terms = null;
			for (String tag : tags) {
				list = retrieveUserPapersByTag(tag, stmt, rs);
				//System.out.println(tag + "\tnum\t" + list.size());
				if (list.size() == 0)
					continue;
				terms = reader.terms();
				while (terms.next()) {
					//Term term = terms.term();
					String termString = terms.term().text();
					double up = 0, down = 0;
					TermFreqVector tfv = null;
					for (Integer docId : list) {
						tfv = reader.getTermFreqVector(docId, "content");
						if (tfv == null)
							continue;
						int idx = tfv.indexOf(termString);
						if (idx == -1)
							continue;
						int[] fvector = tfv.getTermFrequencies();
						int tf = fvector[idx];
						up += tf;
						for (int f : fvector) {
							down += f;
						}
					}
					if (up == 0 && down == 0)
						continue;
					double score = ((double) (up + 1)) / (down + termNum);
					//System.out.println(tag + "\t" + termString + "\t" + score);
					writer.write(tag + "\t" + termString + "\t" + score);
					writer.newLine();
				}

			}

		} finally {
			writer.flush();
			writer.close();
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException sqlEx) {
				} // ignore
				rs = null;
			}

			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException sqlEx) {
				} // ignore
				stmt = null;
			}
		}
		reader.close();
	}

	public static void main(String[] args) throws Exception {
		//String user = "1";
		Class.forName("com.mysql.jdbc.Driver").newInstance();
		String url = "jdbc:mysql://localhost:3306/" + "bibsonomy";
		String dbuser = "root";
		String dbpass = "123456";
		Connection con = (Connection) DriverManager.getConnection(url, dbuser,
				dbpass);
		List<String> users = TestUserSelection.retrieveTestUsers();
		for (String user : users) {

			System.out.println("build title model test user\t" + user);
			BuildTitleModel app = new BuildTitleModel(user, con);
			app.build();
			app.clear();
		}
	}

}
